package com.logic.modular.game.battle.process.skillEffectHandle.impl;

import com.logic.modular.game.battle.info.roundInfo.PvpBattleStatisticsInfoServiceImpl;
import com.logic.modular.game.battle.info.roundInfo.domain.PvpBattleStatisticsInfo;
import com.logic.modular.game.battle.info.roundInfo.dto.PvpBattleStatisticsPlayerInfo;
import com.logic.modular.game.battle.panel.Battle;
import com.logic.modular.game.battle.panel.attribute.PlayerHeroAttributeServiceImpl;
import com.logic.modular.game.battle.process.battleStage.actionPhase.actionPhase2.item.ReleaseSkillService;
import com.logic.modular.game.battle.process.domain.OrdinaryAttackInfo;
import com.logic.modular.game.battle.process.domain.Reason;
import com.logic.modular.game.battle.process.skillEffectHandle.base.EffectHandle2;
import com.logic.modular.game.battle.panel.attribute.domain.PlayerHeroAttribute;
import com.logic.modular.gameCore.match.battle.service.impl.CoreCombatFormulaServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 64
 * 普通攻击
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class OrdinaryAttackStrategy {
    private final PlayerHeroAttributeServiceImpl attributeService;
    private final ReleaseSkillService releaseSkillService;
    @Resource
    private StatusStrategy.Status45 status45;
    @Resource
    private CoreCombatFormulaServiceImpl coreCombatFormulaService;
    @Resource
    private EffectHandle2 effectHandle2;
    @Resource
    private PvpBattleStatisticsInfoServiceImpl pvpBattleStatisticsInfoServiceImpl;

    public List<OrdinaryAttackInfo> apply(
            @NotNull(message = "战斗编号不能为空") String battleUUID,
            @NotNull(message = "进行普通攻击的武将") Long playerHeroId
    ) {
        Battle battle = Battle.get(battleUUID);
        List<OrdinaryAttackInfo> list = new ArrayList<>();
        PlayerHeroAttribute attribute = attributeService.selectCache(battleUUID, playerHeroId);

        list.add(apply(attribute));
        Reason doubleHitUsed = attributeService.statusUseAndRefresh(attribute, 37L);// 连击
        if (doubleHitUsed.isSuccess()) {
            list.add(apply(attribute));
        }
        long sum = list.stream().mapToLong(item -> item.getHurt() == null ? 0 : item.getHurt()).sum();
        int size = list.size();
        PvpBattleStatisticsInfo byId = pvpBattleStatisticsInfoServiceImpl.getById(battle.getBattleId());
        Integer rankCamp = attribute.getRankCamp();

        PvpBattleStatisticsPlayerInfo.HeroInfo heroInfo = null;
        if (rankCamp == 0) {
            heroInfo = byId.defendPlayerInfo.getHeroInfo(playerHeroId);
            heroInfo.killCount += sum;
            byId.defendPlayerInfo.heroInfoMap.put(playerHeroId, heroInfo);
            pvpBattleStatisticsInfoServiceImpl.saveCache(byId);
        } else if (rankCamp == 1) {
            heroInfo = byId.attackPlayerInfo.heroInfoMap.get(playerHeroId);
            heroInfo.killCount += sum;
            byId.attackPlayerInfo.heroInfoMap.put(playerHeroId, heroInfo);
            pvpBattleStatisticsInfoServiceImpl.saveCache(byId);
        }
        return list;
    }

    /**
     * 发动一次普通攻击伤害
     *
     * @param actWJAttribute 行动英雄属性
     * @return 普通攻击信息
     */
    public OrdinaryAttackInfo apply(
            PlayerHeroAttribute actWJAttribute
    ) {
        OrdinaryAttackInfo ordinaryAttackInfo = new OrdinaryAttackInfo();

        Integer rankOrder = actWJAttribute.getRankOrder();

        // 防守方
        List<PlayerHeroAttribute> defCamp = attributeService.listCache(actWJAttribute.getBattleUUID()).stream()
                .filter(item -> !item.getRankCamp().equals(actWJAttribute.getRankCamp()) && item.getCurrentForce() > 0)
                .collect(Collectors.toList());
        PlayerHeroAttribute targetAttribute = null;
        if (rankOrder == 1) {
            targetAttribute = defCamp.stream()
                    .min(Comparator.comparing(PlayerHeroAttribute::getRankOrder))
                    .orElse(null);
        } else if (rankOrder == 2) {
            List<PlayerHeroAttribute> collect = defCamp.stream().sorted(Comparator.comparing(PlayerHeroAttribute::getRankOrder)).collect(Collectors.toList());
            targetAttribute = collect.stream()
                    .filter(item -> item.getRankOrder().equals(rankOrder))
                    .findFirst()
                    .orElse(collect.stream()
                            .filter(item -> !item.getRankOrder().equals(rankOrder))
                            .findFirst()
                            .orElse(null)
                    );
        } else if (rankOrder == 3) {
            targetAttribute = defCamp.stream()
                    .max(Comparator.comparing(PlayerHeroAttribute::getRankOrder))
                    .orElse(null);
        }

        if (targetAttribute == null) {
            ordinaryAttackInfo.setIsSuccessful(Boolean.FALSE);
            return ordinaryAttackInfo;
        }
        ordinaryAttackInfo.setTargetPlayerHeroId(targetAttribute.getId());

        Long currentForce = actWJAttribute.getCurrentForce();
        Double att = actWJAttribute.getAtt();
        Double igPhysicalDefense = actWJAttribute.getIgPhysicalDefense();
        double physicsAttackIncrease =
                actWJAttribute.obtainPhysicsAttackIncrease() - targetAttribute.obtainPhysicsAttackDecrease();
        Double def = targetAttribute.getDef();
        double physics = coreCombatFormulaService.getPhysics(
                currentForce,
                att,
                igPhysicalDefense,
                1.0,
                physicsAttackIncrease,
                def
        );
        ordinaryAttackInfo.setTroops(currentForce);
        targetAttribute.attributeUpdate(
                "currentForce",
                -physics,
                0,
                1,
                64L);
        actWJAttribute.attributeUpdate(
                "currentForce",
                -physics,
                1,
                1,
                64L);
        attributeService.saveCache(actWJAttribute);
        attributeService.saveCache(targetAttribute);
        effectHandle2.effectTriggerBy("普通攻击", actWJAttribute, targetAttribute);

        status45.apply(actWJAttribute, targetAttribute, defCamp);
        ordinaryAttackInfo.skill4.addAll(releaseSkillService.heroReleaseSkills(
                actWJAttribute.getBattleUUID(),
                actWJAttribute,
                4,
                defCamp
        ));
        ordinaryAttackInfo.addHurt((long) physics);
        ordinaryAttackInfo.setTargetTroops(targetAttribute.getCurrentForce());
        return ordinaryAttackInfo;
    }
}
